package impl

import (
	"context"
	"github.com/starmotioncf/soutchatinternal/constant"
	"github.com/starmotioncf/soutchatinternal/errcode"
	"github.com/starmotioncf/soutchatinternal/model"
	"github.com/starmotioncf/soutchatinternal/repository"
	"github.com/starmotioncf/soutchatinternal/service"
	"sync"

	//"github.com/beego/beego/logs"
	"github.com/gin-gonic/gin"
)

type walletService struct {
	*service.Service
	walletRepo repository.WalletRepository
	userRepo   repository.UserRepository
	goldRepo   repository.GoldRepository

	mux       sync.RWMutex
	freezeUid map[uint64]struct{}
}

func NewWalletService(s *service.Service, walletRepo repository.WalletRepository,
	userRepo repository.UserRepository, goldRepo repository.GoldRepository) service.WalletService {
	_s := &walletService{
		Service:    s,
		walletRepo: walletRepo,
		userRepo:   userRepo,
		goldRepo:   goldRepo,
	}
	_s.init()
	// s.internal.setWallet(_s)
	// s.materials.Register(material.Gold, &goldMaterial{wallet: _s})
	// s.materials.Register(material.Diamond, &diamondMaterial{wallet: _s})
	return nil
}

func (s *walletService) init() {
	//s.eventBus.Subscribe(event2.WalletGoldChangeEvent, event.ISubscribeFunc(s.eventGoldChange))
}

// func (s *walletService) eventGoldChange(evt event.IEvent) {
// 金币变动后的预警监控
//var pl event2.WalletGoldChangePayload
//var ok bool
//if pl, ok = evt.Payload().(event2.WalletGoldChangePayload); !ok {
//	return
//}
//day := pl.Record.Time.Format(time.DateOnly)
//step := float64(0.2)
////平台日流水监控预警
//if pl.RType.DailyWarningThreshold > 0 {
//	rk := fmt.Sprintf(redis.GOLD_RTYPE_DAY_TOTAL_VALUE, day)
//	v, _ := redis.HINCRBY_ttl(rk, pl.Record.RType, pl.Record.Number, 86400)
//	if int64(v) >= pl.RType.DailyWarningThreshold {
//		rkN := fmt.Sprintf(redis.GOLD_RTYPE_DAY_TOTAL_VALUE_NOTIFY_NUM, day)
//		vN, _ := redis.HGET_int64(rkN, pl.Record.RType)
//		if int64(v) >= int64((float64(vN)*step)*float64(pl.RType.DailyWarningThreshold))+pl.RType.DailyWarningThreshold {
//			redis.HINCRBY_ttl(rkN, pl.Record.RType, 1, 86400)
//			notice.Send(notice.DefaultTopic, notify.P4, fmt.Sprintf("[%s](rType:%d) 今日流水[%d]超出设定预警值[%d]", pl.RType.Name, pl.Record.RType, v, pl.RType.DailyWarningThreshold))
//		}
//	}
//}
////用户日流水监控预警
//if pl.RType.UserDailyWarningThreshold > 0 {
//	rk := fmt.Sprintf(redis.GOLD_RTYPE_USER_DAY_TOTAL_VALUE, day)
//	fd := fmt.Sprintf("%d-%d", pl.Record.Uid, pl.Record.RType)
//	v, _ := redis.HINCRBY_ttl(rk, fd, pl.Record.Number, 86400)
//	if int64(v) >= pl.RType.UserDailyWarningThreshold {
//		rkN := fmt.Sprintf(redis.GOLD_RTYPE_USER_DAY_TOTAL_VALUE_NOTIFY_NUM, day)
//		vN, _ := redis.HGET_int64(rkN, fd)
//		if int64(v) >= int64((float64(vN)*step)*float64(pl.RType.UserDailyWarningThreshold))+pl.RType.UserDailyWarningThreshold {
//			redis.HINCRBY_ttl(rkN, fd, 1, 86400)
//			notice.Send(notice.DefaultTopic, notify.P4, fmt.Sprintf("[%s](rType:%d) 用户[%d]今日流水[%d]超出设定预警值[%d]", pl.RType.Name, pl.Record.RType, pl.Record.Uid, v, pl.RType.UserDailyWarningThreshold))
//		}
//	}
//}
//return nil

// }

// // OperationGold 操作金币
// func (s *walletService) OperationGold(ctx context.Context, mode constant.WalletAction, gr repository.Record) error {
// 	return s.operationGold(ctx, mode, gr)
// }

// // AddGold 增加金币
// func (s *walletService) AddGold(ctx context.Context, gr repository.Record) error {
// 	return s.operationGold(ctx, constant.WalletActionAdd, gr)
// }

// // CutGold 扣减金币
// func (s *walletService) CutGold(ctx context.Context, gr repository.Record) error {
// 	return s.operationGold(ctx, constant.WalletActionCut, gr)
// }

// // operationGold 操作金币
func (s *walletService) operationGold(ctx *gin.Context, mode constant.WalletAction, gr repository.Record) (err error) {
	//var gType *model.GoldType
	//defer func() {
	//	if err != nil {
	//		if err != repository.ErrGoldNotEnough {
	//			// logs.Error(fmt.Sprintf("gold operation[%d](%s) err: %s", mode, gr.String(), err))
	//		}
	//		return
	//	}
	//	//金币变化事件
	//	// s.eventBus.PublishAsync(event.NewEvent(event2.WalletChangeEvent, event2.WalletChangePayload{RType: *rType, Record: gr}))
	//}()
	//if gr.Number <= 0 {
	//	err = errcode.ErrGoldIsZero
	//	return
	//}
	////检查rtype类型是否正确
	//gType, err = s.checkRType(ctx, mode, constant.WalletTypGold, gr.Typ)
	//if err != nil {
	//	logs.Error("rType不正确", gr.Typ, err.Error())
	//	log.WithContext(ctx).Error("goldTyp不正确:%s", zap.Int("typ", gr.Typ), zap.Error(err))
	//	return err
	//}
	//
	//return s.Transaction.Transaction(ctx, func(ctx context.Context) (err error) {
	//	num := gr.Number
	//	if mode == constant.WalletActionAdd {
	//		err = s.walletRepo.AddGold(ctx, gr)
	//	} else {
	//		num = -num
	//		err = s.walletRepo.CutGold(ctx, gr)
	//	}
	//	if err != nil {
	//		return err
	//	}
	//	//插入金币记录
	//	err = s.walletRepo.CreateGoldRecord(ctx, &model.VcGoldRecord{
	//		Uid:      gr.Uid,
	//		Number:   num,
	//		RType:    gr.RType,
	//		StatDate: gr.Time.Format(time.DateOnly),
	//		Ts:       gr.Time.Unix(),
	//	})
	//	if err != nil {
	//		return
	//	}
	//	return s.walletRepo.AddGoldStatNew(ctx, &model.VcGoldRecordStatNew{
	//		RType:     gr.RType,
	//		Statdate:  gr.Time.Format(time.DateOnly),
	//		Number:    num,
	//		UpdatedAt: gr.Time.Unix(),
	//	})
	//})
	return nil
}

// // OperationGemstone 操作钻石
// func (s *walletService) OperationGemstone(ctx context.Context, mode constant.WalletAction, gr repository.Record) error {
// 	return s.operationGemstone(ctx, mode, gr)
// }

// // AddGemstone 增加钻石
// func (s *walletService) AddGemstone(ctx context.Context, gr repository.Record) error {
// 	return s.operationGemstone(ctx, constant.WalletActionAdd, gr)
// }

// // CutGemstone 扣减钻石
// func (s *walletService) CutGemstone(ctx context.Context, gr repository.Record) error {
// 	return s.operationGemstone(ctx, constant.WalletActionCut, gr)

// }

// // operationGemstone 操作钻石
// func (s *walletService) operationGemstone(ctx context.Context, mode constant.WalletAction, gr repository.Record) (err error) {
// 	var rType *model.VcGoldType
// 	defer func() {
// 		if err != nil {
// 			logs.Error(fmt.Sprintf("gemstone operation[%d](%s) err: %s", mode, gr.String(), err))
// 			return
// 		}
// 		//钻石变化事件
// 		s.eventBus.Publish(event.NewEvent(event2.WalletChangeEvent, event2.WalletChangePayload{RType: *rType, Record: gr}))
// 	}()
// 	if gr.Number <= 0 {
// 		err = repository.ErrGoldIsZero
// 		return
// 	}
// 	//检查rtype类型是否正确
// 	rType, err = s.checkRType(mode, constant.WalletTypGemstone, gr.RType)
// 	if err != nil {
// 		return err
// 	}
// 	//检查是否被冻结
// 	//if s.isFreeze(ctx, gr) {
// 	//	return repository.ErrGoldFreeze
// 	//}

// 	return s.tm.Transaction(ctx, func(ctx context.Context) (err error) {
// 		num := gr.Number
// 		if mode == constant.WalletActionAdd {
// 			err = s.walletRepo.AddGemstone(ctx, gr)
// 		} else {
// 			num = -gr.Number
// 			err = s.walletRepo.CutGemstone(ctx, gr)
// 		}
// 		if err != nil {
// 			return err
// 		}
// 		//插入金币记录
// 		err = s.walletRepo.CreateGemstoneRecord(ctx, &model.VcGemstoneRecord{
// 			Uid:      gr.Uid,
// 			Number:   num,
// 			RType:    gr.RType,
// 			StatDate: gr.Time.Format(time.DateOnly),
// 			Ts:       gr.Time.Unix(),
// 		})
// 		if err != nil {
// 			return
// 		}
// 		return s.walletRepo.AddGoldStatNew(ctx, &model.VcGoldRecordStatNew{
// 			RType:     gr.RType,
// 			Statdate:  gr.Time.Format(time.DateOnly),
// 			Number:    num,
// 			UpdatedAt: gr.Time.Unix(),
// 		})
// 	})
// }

// func (s *walletService) GetGold(ctx context.Context, uid uint64) int64 {
// 	gold, _ := s.walletRepo.GetGold(ctx, uid)
// 	return gold
// }

// func (s *walletService) GetGemstone(ctx context.Context, uid uint64) int64 {
// 	gemstone, _ := s.walletRepo.GetGemstone(ctx, uid)
// 	return gemstone
// }

func (s *walletService) checkRType(ctx context.Context, mode constant.WalletAction, cate uint8, gTyp int) (typInfo *model.GoldType, err error) {
	//rTypeInfo, err = GetGoldRType(rType)
	typInfo, err = s.goldRepo.GetGoldType(ctx, gTyp)
	if err == nil || typInfo == nil {
		return typInfo, errcode.ErrGoldTypNotExists
	}
	//是否被 后台关闭这个rtype了
	if typInfo.Status != 1 {
		return typInfo, repository.ErrGoldTypClosed
	}
	//操作类型，增加或者扣减知否对得上
	if typInfo.Mode != mode {
		return typInfo, repository.ErrGoldTypModeError
	}
	//对象类型，金币还是钻石还是美金
	if typInfo.Cate != cate {
		return typInfo, repository.ErrGoldTypError
	}
	return typInfo, nil
}

// // AddAgentGold 增加代理金币
// func (s *walletService) AddAgentGold(ctx context.Context, gr repository.AgentRecord) error {
// 	return s.operationAgentGold(ctx, constant.WalletActionAdd, gr)
// }

// // CutAgentGold 扣减代理金币
// func (s *walletService) CutAgentGold(ctx context.Context, gr repository.AgentRecord) error {
// 	return s.operationAgentGold(ctx, constant.WalletActionCut, gr)
// }

// // AgentTransferGold 代理金币用户转帐
// //func (s *walletService) AgentTransferGold(ctx context.Context, agentUid, toUid uint64) error {
// //
// //}

// // GetAgentGold 获取代理金币
// func (s *walletService) GetAgentGold(ctx context.Context, uid uint64) int64 {
// 	gold, _ := s.walletRepo.GetAgentGold(ctx, uid)
// 	return gold
// }

// // operationAgentGold 操作代理金币
// func (s *walletService) operationAgentGold(ctx context.Context, mode constant.WalletAction, gr repository.AgentRecord) (err error) {
// 	ctx, span := otlp.Start(ctx, "walletService:operationAgentGold")
// 	defer span.End()
// 	defer func() {
// 		if err != nil {
// 			span.AddEvent("operation error:" + err.Error())
// 			if errors.Is(err, repository.ErrGoldNotEnough) {
// 				logs.Error(fmt.Sprintf("agent gold operation[%d](%s) err: %s", mode, gr.String(), err))
// 			}
// 			return
// 		}
// 		span.AddEvent("operation success")
// 	}()
// 	if gr.Number <= 0 {
// 		err = repository.ErrGoldIsZero
// 		return
// 	}
// 	rgn := s.userRepo.GetRegion(ctx, gr.Uid)
// 	dollarRate := region2.Region(rgn).Dollar2GoldRate()
// 	return s.tm.Transaction(ctx, func(ctx context.Context) (err error) {
// 		num := gr.Number
// 		if mode == constant.WalletActionAdd {
// 			err = s.walletRepo.AddAgentGold(ctx, gr)
// 		} else {
// 			num = -num
// 			err = s.walletRepo.CutAgentGold(ctx, gr)
// 		}
// 		if err != nil {
// 			return err
// 		}
// 		//插入金币记录
// 		return s.walletRepo.CreateAgentGoldRecord(ctx, &model.VcAgentGoldRecord{
// 			SendUid: gr.TargetUid,
// 			RecUid:  gr.Uid,
// 			Type:    gr.RType,
// 			Gold:    gr.Number,
// 			Dollar:  gr.Number / int64(dollarRate),
// 			Remark:  gr.Remark,
// 			Ts:      gr.Time.Unix(),
// 		})
// 	})
// }
